package com.hrt.datasender.datacollect.drive.modbus.tcp;

import com.btcode.common.PropertiesUnit;
import com.btcode.db.result.Row;
import com.btcode.schedule.ScheduleManager;
import com.hrt.datasender.datacollect.drive.DriveConfigModel;
import com.hrt.datasender.datacollect.drive.DriveParameterMetadata;
import com.hrt.datasender.datadao.model.BcDeviceConfigModel;
import com.hrt.datasender.datadao.model.BcDeviceMonitorParamModel;
import com.hrt.datasender.datadao.model.BcDevicesModel;
import com.hrt.datasender.datadao.model.BdSourceModel;
import com.hrt.datasender.web.bdplccontrol.BdPlcControlService;
import com.hrt.datasender.web.bdplccontrol.BdPlcDataSingleModel;
import com.hrt.db.DBManager;
import com.hrt.serial.modbus.ModbusDataDecodePlcTcp;
import com.hrt.serial.modbus.ModbusDataModel;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * modbusTCP-PLC驱动
 * 
 * @author wencheng
 *
 */
public class ModbusTcpPlcDrive extends NetBaseDrive {

    protected ModbusDataDecodePlcTcp decode = new ModbusDataDecodePlcTcp();

    @Override
    public String getNote() {
        return null;
    }

    @Override
    public String getDriveName() {
        return "ModbusTCP-PLC驱动";
    }

    @Override
    public String getConsStr() {
        return "0/10 * * * * ?";
    }

    @Override
    public List<BdSourceModel> processNetExportData(byte[] data, HashMap<Integer, String> paramCodeMap,
            DriveConfigModel deviceConfigs) {
        /**
         * 根据PLC配置表进行数据读取
         */
        List<ModbusDataModel> modbusDataModels = decode.dataModelDecode(data, data.length, deviceConfigs);

        List<BdSourceModel> sourceModels = new ArrayList<>();

        for(ModbusDataModel modbusDataModel:modbusDataModels){
            String paramCodeBus = modbusDataModel.getId();
            String plcPointId = modbusDataModel.getPlcPointId();
            Boolean plcIsMeasValue = modbusDataModel.getPlcIsMeasValue();
            Object value = modbusDataModel.getSingleData();

            BdPlcDataSingleModel plcDataSingleModel = new BdPlcDataSingleModel();
            plcDataSingleModel.setPlcPointId(plcPointId);
            plcDataSingleModel = DBManager.getORMExecuter().getModel(plcDataSingleModel);
            if(plcDataSingleModel==null){
                plcDataSingleModel = new BdPlcDataSingleModel();
                plcDataSingleModel.setId(UUID.randomUUID().toString());
                plcDataSingleModel.setPlcPointId(plcPointId);
                plcDataSingleModel.setValue(value+"");
                DBManager.getORMExecuter().create(plcDataSingleModel);
            }
            else{
                plcDataSingleModel.setValue(value+"");
                plcDataSingleModel.setUpdatetime(new Date());
                DBManager.getORMExecuter().update(plcDataSingleModel);
            }

            if(!plcIsMeasValue){
                continue;
            }

            Double dValue = (Double) value;
            BdSourceModel sourModel = new BdSourceModel();
            sourModel.setParamCodeBus(paramCodeBus);
            sourModel.setDatatime(new Date());
            sourModel.setMeasRe(dValue);
            sourceModels.add(sourModel);
        }

        return sourceModels;
    }

    @Override
    public List<DriveParameterMetadata> getParameterMetadata() {
        List<DriveParameterMetadata> params = new ArrayList<>();
        params.add(new DriveParameterMetadata("ip", "IP"));
        params.add(new DriveParameterMetadata("port", "端口"));
        params.add(new DriveParameterMetadata("slaveNo", "从站编号"));
        params.add(new DriveParameterMetadata("startNo", "起始位置"));
        params.add(new DriveParameterMetadata("dataLength", "数据长度"));
        params.add(new DriveParameterMetadata("driveInstanceId", "驱动实例ID"));
        params.add(new DriveParameterMetadata("functionCode", "功能码"));
        return params;
    }

    @Override
    protected void beforeInit(BcDevicesModel device, List<BcDeviceMonitorParamModel> params,
            List<BcDeviceConfigModel> configs) {
        // TODO Auto-generated method stub

    }

    @Override
    protected void registerAskDataJob(BcDevicesModel device, DriveConfigModel configs) {
        HashMap<String, String> configsMap = configs.getConfig();
        /**
         * 1、获取PLC点位配置
         */
        int startNo = Integer.parseInt(configsMap.get("startNo"));
        int dataLength = Integer.parseInt(configsMap.get("dataLength"));
        int endNo = startNo + dataLength;
        String sql = "SELECT t.ID, t.PARAM_CODE_BUS, t.POINT_NAME, t.POINT_DATA_TYPE, t.POINT_POSITION,t.IS_MEAS_VALUE\n" +
            "  FROM bc_plc_point_config t\n" +
            " WHERE t.point_position >= " + startNo +
            "   AND t.point_position < " + endNo;
        List<Row> plcPointRows = DBManager.getDataExecuter().queryList(sql,null);

        /**
         * 2、进行PLC偏移
         */
        int plcDeviation = 0;
        String strPlcDeviation = PropertiesUnit.getValue("plcDeviation");
        if(strPlcDeviation!=null&&!"".equals(strPlcDeviation)){
            plcDeviation = Integer.parseInt(strPlcDeviation);
        }

        if(plcDeviation!=0){
            startNo = Integer.parseInt(configsMap.get("startNo"));
            startNo = startNo + plcDeviation;
            configsMap.put("startNo",startNo+"");
            for(Row row:plcPointRows){
                double pointPosition = row.getSafeDouble("POINT_POSITION");
                pointPosition = pointPosition + plcDeviation;
                row.setValue("POINT_POSITION",pointPosition);
            }
        }

        configs.setConfig(configsMap);
        configs.setPlcPointRows(plcPointRows);

        HashMap<String, Object> data = new HashMap<>();
        data.put("device", device);
        data.put("deviceConfigs", configs);
        String jobName = getClass().getName() + "." + device.getId();
        ScheduleManager.getInstance().addJob(ModbusNetDataAsker.class, getConsStr(), data, jobName);
    }
}
